#!/usr/bin/env bash

include "libs/test.sh"

function changelog:display()
{
    local since="$1"
    local until="$2"

    local -a hashs types modules infos breakings
    local -a feature bugfix docs other
    local length=0


    changelog:get_commits $since $until
    changelog:classify_commits
    changelog:display_commits
}

function changelog:display:test()
{
    test:run_snapshot changelog:display 2d50afa72c d11b077117
}
test:register_test changelog:display:test

function changelog:get_commits()
{
    local since="$1"
    local until="$2"

    local commit hash type info module
    while read commit; do
        # ae9856a: chore(help): 帮助信息的缩进修改为4个空格
        hash="${commit%%: *}"
        commit="${commit#*: }"
        type="${commit%%: *}"
        info="${commit#*: }"

        breaking="${type:$(( ${#A} - 1 ))}"
        if [ "$breaking" != "!" ]; then
            breaking=""
        fi
        module="${type#*(}"
        module="${module%%)*}"
        if [ "$module" = "$type" ]; then
            module=""
        fi

        type="${type%%(*}"
        type="${type%%!*}"

        hashs[$length]="$hash"
        types[$length]="$type"
        modules[$length]="$module"
        infos[$length]="$info"
        breakings[$length]="$breaking"
        (( length++ ))
    done <<< $(git log --format="%h: %s" --no-merges --first-parent "$since..$until")
}

function changelog:classify_commits()
{
    for ((i = 0; i < $length; i++)); do
        local type=${types[$i]}

        if [ "$type" = "feature" ]; then
            feature+=($i)
        elif [ "$type" = "bugfix" ]; then
            bugfix+=($i)
        elif [ "$type" = "docs" ]; then
            docs+=($i)
        else
            other+=($i)
        fi
    done
}

function changelog:display_commit()
{
    local index=$1
    local fmt hash module type info
    hash="$(cctl y)${hashs[$index]}$(cctl 0)"
    if [ "${modules[$index]}" != "" ]; then
        module="[$(cctl g)${modules[$index]}$(cctl 0)]"
        fmt="    - %-18s %-30s %s\n"
    else
        module=""
        fmt="    - %-18s %-21s %s\n"
    fi
    type=${types[$index]}
    if [ "$type" = "feature" ] || [ "$type" = "bugfix" ] || [ "$type" = "docs" ]; then
        info="$(cctl c)${infos[$index]}$(cctl 0)"
    else
        info="$(cctl w "4;")$type$(cctl 0): $(cctl c)${infos[$index]}$(cctl 0)"
    fi

    if [ "${breakings[$index]}" = "!" ]; then
        info+=" $(cctl r "1;4;") 重大更新 $(cctl 0)"
    fi

    printf "$fmt" "$hash" "$module" "$info"

    if [ "${breakings[$index]}" = "!" ]; then
        local result="$(git log --format="%b" --no-merges --first-parent "${hashs[$index]}^..${hashs[$index]}")"
        sed "s/^/        $(cctl b)/g" <<< $result | sed "s/$/$(cctl 0)/g"
    fi
}

function changelog:display_commits()
{
    if (( ${#feature[*]} > 0 )); then
        printf "$(cctl d "1;")Feature:$(cctl 0)\n"
        for i in ${feature[*]}; do
            changelog:display_commit $i
        done
    fi

    if (( ${#bugfix[*]} > 0 )); then
        printf "\n$(cctl d "1;")Bugfix:$(cctl 0)\n"
        for i in ${bugfix[*]}; do
            changelog:display_commit $i
        done
    fi

    if (( ${#docs[*]} > 0 )); then
        printf "\n$(cctl d "1;")Documentation:$(cctl 0)\n"
        for i in ${docs[*]}; do
            changelog:display_commit $i
        done
    fi

    if (( ${#other[*]} > 0 )); then
        printf "\n$(cctl d "1;")Other:$(cctl 0)\n"
        for i in ${other[*]}; do
            changelog:display_commit $i
        done
    fi
}
